﻿using GrapeCity.Forguncy;
using GrapeCity.Forguncy.ServerApi;
using Microsoft.AspNetCore.Http;
using System;
using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using System.IO.Compression;
using Newtonsoft.Json.Linq;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;


namespace TB单点登录
{
    public class dgwebapi : ForguncyApi
    {
        [Get]
        public async Task SSO()
        {
            //获取请求的查询字符串参数提取code参数
            var queries = this.Context.Request.Query;
            var code = queries["code"].ToString();
            DingdingConfig config = GetConfig();
            //获取配置文件的 
            string? appID = config.AppID;  //应用ID
            string? appSecret = config.AppSecret;  //应用的secret
            string? redirectUri = config.redirectUri; //对方302跳转自己的服务器webapi地址，携带code信息用于下一步做认证
            string? SsoPassword = config.SsoPassword; //自己的活字格单点登录密码
            string? pageName = config.pageName; //最后302跳转的页面名称

            //判断code 是否为空或为 null,如果是，它会调用 GetRedirectUrl 方法，传入 config.Appkey 作为参数，获取一个重定向的 URL，将用户重定向到这个 URL，最后返回以结束当前操作
            if (string.IsNullOrEmpty(code))
            {
                Trace.WriteLine("未登录302跳转--Code is null or empty.");
                string outurl = $"https://open.teambition.com/api/oauth/sso?app_id={appID}&redirect_uri={UrlEncode(redirectUri)}&state=state";
                this.Context.Response.Redirect(outurl);
                return;
            }
            else
            {
                //调用方法计算tb的token
                var appAccessToken = GenerateJwtToken(appID, appSecret);
                var grantType = "authorization_code"; // 或 "refresh_token"
                //获取用户token
                var client = new Teambitionusertoken(appAccessToken);
                string usertoken = "";
                string userid = "";
                var userName = "";
                try
                {
                    var result = await client.GetUserAccessTokenAsync(code, grantType);
                    if (result.code == 200)
                    {
                        usertoken = result.result.accessToken;
                        userid = result.result.userId;
                    }
                    else
                    {
                        Trace.WriteLine($"LoginResponse error {JsonConvert.SerializeObject(result.errorMessage)} code: [{code}]");
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine($"LoginResponse error {JsonConvert.SerializeObject(ex.Message)} code: [{code}]");
                    return;
                }

                //获取用户信息
                var client1 = new TeambitionApiClient(appAccessToken);
                try
                {
                    var result1 = await client1.GetUserInfoAsync(usertoken);
                    if (result1.code == 200)
                    {
                        userid = result1.result.userId;
                        userName = result1.result.name;
                    }
                    else
                    {
                        Trace.WriteLine($"LoginResponse error {JsonConvert.SerializeObject(result1.errorMessage)} code: [{code}]");
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine($"UserIdResponse error {JsonConvert.SerializeObject(ex.Message)} code: [{code}]");
                    return;
                }

                //查询系统使用存在用户
                var userInfo = await this.UserInfos.GetUserInfoAsync(userid);
                if (userInfo == null)
                {
                    //如果用户名不存在则添加用户
                    var dic = new Dictionary<string, string>();
                    var aa01 = this.UserInfos.AddUserAsync(userid, "123456", "example1@example.com", userName, dic);
                }

                //var url2 = await SendPostRequestAsync(userid, SsoPassword, pageName,redirectUri);
                var url2 = GetForguncySSOUrl(userid, SsoPassword, pageName, redirectUri);
                url2 = Uri.EscapeUriString(url2); // 编码 URL
                this.Context.Response.Redirect(url2);

            }
            
        }

        //活字格获取用户token
        private static readonly HttpClient httpClient = new HttpClient();
        public async Task<string> SendPostRequestAsync(string userName, string password, string pageName, string redirectUri)
        {
            var uri = "http://localhost";
            if (this.Context.Request.IsHttps)
            {
                uri = "https://localhost";
            }
            uri = uri + ":" + this.Context.Request.Host.Port.GetValueOrDefault(80);

            var localUrl = uri + this.Context.Request.PathBase.Value +  "/SSO/GetUserToken";

            // 创建 Uri 对象
            Uri uri01 = new Uri(redirectUri);

            // 提取完整的域名（包含协议） 
            string fullDomain = $"{uri01.Scheme}://{uri01.Host}";
            // 创建请求内容
            var jsonContent = JsonConvert.SerializeObject(new
            {
                userName = userName,
                password = password
            });
            // 使用 StringContent 发送 JSON 数据
            var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");

            // 发送 POST 请求
            try
            {
                HttpResponseMessage response = await httpClient.PostAsync(localUrl, content);
                response.EnsureSuccessStatusCode();
                // 读取响应内容
                string responseBody = await response.Content.ReadAsStringAsync();
                //var baseUrl = this.Context.Request.Scheme + "://" + this.Context.Request.Host + this.Context.Request.PathBase.Value;fullDomain //使用请求响应的信息作为302跳转地址
                var baseUrl = fullDomain;
                if (!string.IsNullOrEmpty(pageName))
                {
                    baseUrl += "/" + UrlEncode(pageName);
                }

                if (responseBody.StartsWith("Error:"))
                {
                    Trace.WriteLine("Dingding SSO Error: " + responseBody);
                    return responseBody;
                }
                return baseUrl + "?token=" + responseBody;
            }
            catch (HttpRequestException e)
            {
                return ($"请求错误: {e.Message}");
            }
            
        }

        private string GetForguncySSOUrl(string userName, string ssoPassword, string pageName, string redirectUri)
        {
            var uri = "http://localhost";
            if (this.Context.Request.IsHttps)
            {
                uri = "https://localhost";
            }
            uri = uri + ":" + this.Context.Request.Host.Port.GetValueOrDefault(8081);

            var localUrl = uri + this.Context.Request.PathBase.Value;
            var password = ssoPassword;  // 这个密码是单点登录密码
            HttpWebRequest rq = HttpWebRequest.Create(localUrl + "/SSO/GetUserToken") as HttpWebRequest;
            rq.Method = WebRequestMethods.Http.Post;
            rq.Accept = "application/json";
            rq.ContentType = "application/json";
            var loginStr = "{userName:\"" + userName + "\", password:\"" + password + "\"}";
            var data = Encoding.UTF8.GetBytes(loginStr);
            using (Stream stream = rq.GetRequestStream())
            {
                stream.Write(data, 0, data.Length);
            }
            var response = rq.GetResponse();
            var token = new StreamReader(response.GetResponseStream()).ReadToEnd();

            // 创建 Uri 对象
            Uri uri01 = new Uri(redirectUri);

            // 提取完整的域名（包含协议）
            string fullDomain = $"{uri01.Scheme}://{uri01.Host}";

            // var baseUrl = this.Context.Request.Scheme + "://" + this.Context.Request.Host + this.Context.Request.PathBase.Value; 
            var baseUrl = fullDomain;
            if (!string.IsNullOrEmpty(pageName))
            {
                baseUrl += "/" + pageName;
            }

            if (token.StartsWith("Error:"))
            {
                Trace.WriteLine("Dingding SSO Error: " + token);
                return baseUrl;
            }

            return baseUrl + "?token=" + token;
        }

        //读取配置文件
        private static DingdingConfig GetConfig()
        {
            var assembly = typeof(dgwebapi).Assembly.Location;

            var configFile = Path.Combine(Path.GetDirectoryName(assembly), "config.json");
 
            return JsonConvert.DeserializeObject<DingdingConfig>(File.ReadAllText(configFile));

        }
        //TB计算token
        private static string GenerateJwtToken(string appId, string secretKey)
        {
            // 设置密钥
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretKey));

            // 设置签名算法
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            // 设置有效负载
            var claims = new[]
            {
            new Claim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()), // 发行时间
            new Claim("exp", DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds().ToString()), // 过期时间
            new Claim("_appId", appId) // 应用 ID
        };

            // 创建JWT Token
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(claims),
                Expires = DateTime.UtcNow.AddHours(1),
                SigningCredentials = credentials
            };

            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenString = tokenHandler.CreateToken(tokenDescriptor);
            return tokenHandler.WriteToken(tokenString);
        }

        private static string UrlEncode(string str)
        {
            StringBuilder sb = new StringBuilder();
            byte[] byStr = System.Text.Encoding.UTF8.GetBytes(str); //默认是System.Text.Encoding.Default.GetBytes(str)
            for (int i = 0; i < byStr.Length; i++)
            {
                sb.Append(@"%" + Convert.ToString(byStr[i], 16));
            }

            return (sb.ToString());
        }

    }

    //定义配置文件内容参数
    public class DingdingConfig
    {
        public string? AppID { get; set; }
        public string? AppSecret { get; set; }
        public string? SsoPassword { get; set; }
        public string? redirectUri { get; set; }
        public string? pageName { get; set; }

    }

    public static class HttpClientHelper
    {
        public static HttpClient CreateHttpClient(string appAccessToken)
        {
            var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", appAccessToken);
            return httpClient;
        }
    }

    //获取用户token
    public class Teambitionusertoken
    {
        private readonly HttpClient _httpClient;

        public Teambitionusertoken(string appAccessToken)
        {
            _httpClient = HttpClientHelper.CreateHttpClient(appAccessToken);
        }

        public async Task<dynamic> GetUserAccessTokenAsync(string code, string grantType, string refreshToken = "", int expires = 86400)
        {
            var requestBody = new
            {
                code,
                expires,
                grantType,
                refreshToken
            };

            var jsonContent = JsonConvert.SerializeObject(requestBody);
            var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");
            try
            {
                // 发送 POST 请求
                var response = await _httpClient.PostAsync("https://open.teambition.com/api/oauth/userAccessToken", content);

                // 检查响应状态码
                response.EnsureSuccessStatusCode(); // 会抛出异常

                var responseContent = await response.Content.ReadAsStringAsync();
                return JsonConvert.DeserializeObject<dynamic>(responseContent);
            }
            catch (HttpRequestException ex)
            {
                throw new Exception($"Request error: {ex.Message}", ex);
            }
        }
    }
    //获取登录用户信息
    public class TeambitionApiClient
    {
        private readonly HttpClient _httpClient;

        public TeambitionApiClient(string appAccessToken)
        {
            _httpClient = HttpClientHelper.CreateHttpClient(appAccessToken);
        }

        public async Task<dynamic> GetUserInfoAsync(string userAccessToken)
        {
            var requestBody = new { userAccessToken };
            var jsonContent = JsonConvert.SerializeObject(requestBody);
            var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");

            var response = await _httpClient.PostAsync("https://open.teambition.com/api/oauth/userInfo", content);

            if (!response.IsSuccessStatusCode)
            {
                throw new Exception($"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}");
            }

            var responseContent = await response.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<dynamic>(responseContent);
        }


    }



}